﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AbstractFactoryPatternExample
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var factory in GetFactories())
            {
                factory.CreateEconomyCar().ShowInfo();
                factory.CreateRacingCar().ShowInfo();
                factory.CreateSUV().ShowInfo();
                Console.ReadLine();
            }
        }

        static IEnumerable<IVehicleFactor> GetFactories()
        {
            var types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (var type in types)
            {
                if (type.GetInterface(typeof(IVehicleFactor).ToString()) != null)
                {
                    yield return Activator.CreateInstance(type) as IVehicleFactor;
                }
            }
        }
    }

    public interface IVehicleFactor
    {
        Vehicle CreateEconomyCar();
        Vehicle CreateRacingCar();
        Vehicle CreateSUV();
    }

    public abstract class Vehicle
    {
        public string Model { get; set; }
        public string Engine { get; set; }
        public string Body { get; set; }

        public abstract void ShowInfo();
    }

    public class FordFactory : IVehicleFactor
    {

        public Vehicle CreateEconomyCar()
        {
            return new FordFocus();
        }

        public Vehicle CreateRacingCar()
        {
            return new FordGT();
        }

        public Vehicle CreateSUV()
        {
            return new FordExplorer();
        }
    }

    public class FordFocus : Vehicle
    {
        public FordFocus()
        {
            this.Model = "Ford Focus";
            this.Engine = "Diesel";
            this.Body = "Economy Car";
        }
        public override void ShowInfo()
        {
            Console.WriteLine("Model: {0}", this.Model);
            Console.WriteLine("Engine: {0}", this.Engine);
            Console.WriteLine("Body: {0}", this.Body);
        }
    }

    public class FordGT : Vehicle
    {
        public FordGT()
        {
            this.Model = "Ford GT";
            this.Engine = "Benzine";
            this.Body = "Racing Car";
        }
        public override void ShowInfo()
        {
            Console.WriteLine("Model: {0}", this.Model);
            Console.WriteLine("Engine: {0}", this.Engine);
            Console.WriteLine("Body: {0}", this.Body);
        }
    }

    public class FordExplorer : Vehicle
    {
        public FordExplorer()
        {
            this.Model = "Ford Explorer";
            this.Engine = "Benzine";
            this.Body = "Off-Road Car";
        }
        public override void ShowInfo()
        {
            Console.WriteLine("Model: {0}", this.Model);
            Console.WriteLine("Engine: {0}", this.Engine);
            Console.WriteLine("Body: {0}", this.Body);
        }
    }
}
